From a0bbd14325db6b36083e7b79e9938b997d060767 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 28 Oct 2017 13:13:31 -0400 Subject: [PATCH] gsk: Scale glyphs in the glyph cache Pass a scale factor when caching glyphs or looking them up in the cache. The glyphs in the cache are rendered with subpixel precision determined by the scale. Update all callers to pass a scale factor according to the window scale. This lets us render crisp glyphs on hidpi systems. --- gsk/gskvulkancolortextpipeline.c | 5 +++-- gsk/gskvulkancolortextpipelineprivate.h | 3 ++- gsk/gskvulkanglyphcache.c | 30 ++++++++++++++++--------- gsk/gskvulkanglyphcacheprivate.h | 3 ++- gsk/gskvulkanrenderer.c | 10 +++++---- gsk/gskvulkanrendererprivate.h | 6 +++-- gsk/gskvulkanrenderpass.c | 10 ++++++--- gsk/gskvulkantextpipeline.c | 5 +++-- gsk/gskvulkantextpipelineprivate.h | 3 ++- 9 files changed, 48 insertions(+), 27 deletions(-) diff --git a/gsk/gskvulkancolortextpipeline.c b/gsk/gskvulkancolortextpipeline.c index 654b30ccef..dd236da880 100644 --- a/gsk/gskvulkancolortextpipeline.c +++ b/gsk/gskvulkancolortextpipeline.c @@ -103,7 +103,8 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * float x, float y, guint start_glyph, - guint num_glyphs) + guint num_glyphs, + float scale) { GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data; int i; @@ -127,7 +128,7 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * GskVulkanColorTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; diff --git a/gsk/gskvulkancolortextpipelineprivate.h b/gsk/gskvulkancolortextpipelineprivate.h index 9a933ef27a..2e46b1c6a8 100644 --- a/gsk/gskvulkancolortextpipelineprivate.h +++ b/gsk/gskvulkancolortextpipelineprivate.h @@ -31,7 +31,8 @@ void gsk_vulkan_color_text_pipeline_collect_vertex_data (Gs float x, float y, guint start_glyph, - guint num_glyphs); + guint num_glyphs, + float scale); gsize gsk_vulkan_color_text_pipeline_draw (GskVulkanColorTextPipeline *pipeline, VkCommandBuffer command_buffer, gsize offset, diff --git a/gsk/gskvulkanglyphcache.c b/gsk/gskvulkanglyphcache.c index 544b26f0b1..c326c568db 100644 --- a/gsk/gskvulkanglyphcache.c +++ b/gsk/gskvulkanglyphcache.c @@ -116,6 +116,7 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass) typedef struct { PangoFont *font; PangoGlyph glyph; + guint scale; /* times 1024 */ } GlyphCacheKey; static gboolean @@ -125,7 +126,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2) const GlyphCacheKey *key2 = v2; return key1->font == key2->font && - key1->glyph == key2->glyph; + key1->glyph == key2->glyph && + key1->scale == key2->scale; } static guint @@ -133,7 +135,7 @@ glyph_cache_hash (gconstpointer v) { const GlyphCacheKey *key = v; - return GPOINTER_TO_UINT (key->font) ^ key->glyph; + return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale; } static void @@ -175,6 +177,8 @@ add_to_cache (GskVulkanGlyphCache *cache, Atlas *atlas; int i; DirtyGlyph *dirty; + int width = value->draw_width * key->scale / 1024; + int height = value->draw_height * key->scale / 1024; for (i = 0; i < cache->atlases->len; i++) { @@ -185,14 +189,14 @@ add_to_cache (GskVulkanGlyphCache *cache, y = atlas->y; y0 = atlas->y0; - if (atlas->x + value->draw_width + 1 >= atlas->width) + if (atlas->x + width + 1 >= atlas->width) { /* start a new row */ y0 = y + 1; x = 1; } - if (y0 + value->draw_height + 1 >= atlas->height) + if (y0 + height + 1 >= atlas->height) continue; atlas->y0 = y0; @@ -209,8 +213,8 @@ add_to_cache (GskVulkanGlyphCache *cache, value->tx = (float)atlas->x / atlas->width; value->ty = (float)atlas->y0 / atlas->height; - value->tw = (float)value->draw_width / atlas->width; - value->th = (float)value->draw_height / atlas->height; + value->tw = (float)width / atlas->width; + value->th = (float)height / atlas->height; value->texture_index = i; @@ -219,8 +223,8 @@ add_to_cache (GskVulkanGlyphCache *cache, dirty->value = value; atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty); - atlas->x = atlas->x + value->draw_width + 1; - atlas->y = MAX (atlas->y, atlas->y0 + value->draw_height + 1); + atlas->x = atlas->x + width + 1; + atlas->y = MAX (atlas->y, atlas->y0 + height + 1); atlas->num_glyphs++; @@ -254,8 +258,9 @@ render_glyph (Atlas *atlas, cairo_glyph_t cg; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - value->draw_width, - value->draw_height); + value->draw_width * key->scale / 1024, + value->draw_height * key->scale / 1024); + cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0); cr = cairo_create (surface); @@ -324,13 +329,15 @@ GskVulkanCachedGlyph * gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, gboolean create, PangoFont *font, - PangoGlyph glyph) + PangoGlyph glyph, + float scale) { GlyphCacheKey lookup_key; GskVulkanCachedGlyph *value; lookup_key.font = font; lookup_key.glyph = glyph; + lookup_key.scale = (guint)(scale * 1024); value = g_hash_table_lookup (cache->hash_table, &lookup_key); @@ -364,6 +371,7 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, key->font = g_object_ref (font); key->glyph = glyph; + key->scale = (guint)(scale * 1024); if (ink_rect.width > 0 && ink_rect.height > 0) add_to_cache (cache, key, value); diff --git a/gsk/gskvulkanglyphcacheprivate.h b/gsk/gskvulkanglyphcacheprivate.h index 3a9cddfbee..6cf223f27d 100644 --- a/gsk/gskvulkanglyphcacheprivate.h +++ b/gsk/gskvulkanglyphcacheprivate.h @@ -20,7 +20,8 @@ GskVulkanImage * gsk_vulkan_glyph_cache_get_glyph_image (GskVulkanGlyphCache GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, gboolean create, PangoFont *font, - PangoGlyph glyph); + PangoGlyph glyph, + float scale); void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache); diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index fcc339fcd4..7bc9431d58 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -350,9 +350,10 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, PangoFont *font, - PangoGlyph glyph) + PangoGlyph glyph, + float scale) { - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph)->texture_index; + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index; } GskVulkanImage * @@ -366,7 +367,8 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, - PangoGlyph glyph) + PangoGlyph glyph, + float scale) { - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph); + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale); } diff --git a/gsk/gskvulkanrendererprivate.h b/gsk/gskvulkanrendererprivate.h index 19f0d3baa5..d86734c9df 100644 --- a/gsk/gskvulkanrendererprivate.h +++ b/gsk/gskvulkanrendererprivate.h @@ -44,7 +44,8 @@ typedef struct guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer, PangoFont *font, - PangoGlyph glyph); + PangoGlyph glyph, + float scale); GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, GskVulkanUploader *uploader, @@ -52,7 +53,8 @@ GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer * GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, - PangoGlyph glyph); + PangoGlyph glyph, + float scale); G_END_DECLS diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 09ba75634c..00f79bebdf 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -90,6 +90,7 @@ struct _GskVulkanOpText guint texture_index; /* index of the texture in the glyph cache */ guint start_glyph; /* the first glyph in nodes glyphstring that we render */ guint num_glyphs; /* number of *non-empty* glyphs (== instances) we render */ + float scale; }; struct _GskVulkanOpPushConstants @@ -406,6 +407,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, op.text.start_glyph = 0; op.text.texture_index = G_MAXUINT; + op.text.scale = gdk_window_get_scale_factor (gsk_renderer_get_window (GSK_RENDERER (renderer))); for (i = 0, count = 0; i < num_glyphs; i++) { @@ -413,7 +415,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, if (gi->glyph != PANGO_GLYPH_EMPTY && !(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) { - texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph); + texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale); if (op.text.texture_index == G_MAXUINT) op.text.texture_index = texture_index; if (texture_index != op.text.texture_index) @@ -1232,7 +1234,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, gsk_text_node_get_x (op->text.node), gsk_text_node_get_y (op->text.node), op->text.start_glyph, - op->text.num_glyphs); + op->text.num_glyphs, + op->text.scale); n_bytes += op->text.vertex_count; } break; @@ -1250,7 +1253,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, gsk_text_node_get_x (op->text.node), gsk_text_node_get_y (op->text.node), op->text.start_glyph, - op->text.num_glyphs); + op->text.num_glyphs, + op->text.scale); n_bytes += op->text.vertex_count; } break; diff --git a/gsk/gskvulkantextpipeline.c b/gsk/gskvulkantextpipeline.c index 5cdeb15a1f..5ca2d7e00c 100644 --- a/gsk/gskvulkantextpipeline.c +++ b/gsk/gskvulkantextpipeline.c @@ -111,7 +111,8 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, float x, float y, guint start_glyph, - guint num_glyphs) + guint num_glyphs, + float scale) { GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data; int i; @@ -135,7 +136,7 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, GskVulkanTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; diff --git a/gsk/gskvulkantextpipelineprivate.h b/gsk/gskvulkantextpipelineprivate.h index 064045e469..47517de03c 100644 --- a/gsk/gskvulkantextpipelineprivate.h +++ b/gsk/gskvulkantextpipelineprivate.h @@ -32,7 +32,8 @@ void gsk_vulkan_text_pipeline_collect_vertex_data (GskVulka float x, float y, guint start_glyph, - guint num_glyphs); + guint num_glyphs, + float scale); gsize gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline, VkCommandBuffer command_buffer, gsize offset, -- 2.30.2